package com.yc.http;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;

public class Demo {

    // http://127.0.0.1:8080/docs/index.html
    static String WEBAPPS;

    public static void main(String[] args) throws IOException, InterruptedException {
        Config config = new Config();
        String value = config.getConfig("Connector.port");
        int port = Integer.parseInt(value);
        WEBAPPS = config.getConfig("Webapps");

        ServerSocket server = new ServerSocket(port);
        System.out.println("服务器监听: " + port);

        // 服务线程
        Thread thread = new Thread(()->{
            try{
                while(true){
                    Socket socket = server.accept();
                    new Thread(()->{
                        try{
                            HttpServletRequest request = new HttpServletRequest(socket);
                            String filepath = WEBAPPS + request.getRequestURI();
                            File file = new File(filepath);
                            if(file.exists()){

                                if (request.getRequestURI().endsWith("/docs/aio.html")) {
                                    // 实现请求转发
                                    request.setRequestURI("/docs/apr.html");
                                } else if (request.getRequestURI().endsWith("/docs/building.html")){
                                    // 响应重定向
                                    sendRedirect(socket,"/docs/proxy-howto.html");
                                    return;
                                } else if (request.getRequestURI().endsWith("/docs/extras.html")){
                                    // 响应重定向
                                    sendRedirect(socket,"http://baidu.com");
                                    return;
                                }
                                response(socket, request);

                            } else {

                                if(request.getRequestURI().endsWith("cookies")){
                                    // 查看cookie数据
                                    showCookies(socket, request);
                                } else if(request.getRequestURI().endsWith("setCookie")){
                                    // 查看cookie数据
                                    setCookies(socket, request);
                                } else{
                                    // 404
                                    respones404(socket, request);
                                }
                            }
                            socket.close();
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                    }).start();

                }
            }catch (IOException e){
                throw new RuntimeException("服务器运行错误!",e);
            }
        });
        // 设置精灵线程
        thread.setDaemon(true);
        thread.start();

        // 控制线程
        Thread ctrlThread = new Thread(()->{
            try {
                ServerSocket ctrlServer = new ServerSocket(8009);
                System.out.println("监听停止信号!");
                Socket socket = ctrlServer.accept();
                // 接收到信息, 则停止服务
                synchronized (Demo.class){
                    Demo.class.notify();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        ctrlThread.setDaemon(true);
        ctrlThread.start();

        // 主线程在此等待, 当主线程接收到停止的信号, 继续执行 => 结束
        synchronized (Demo.class){
            System.out.println("主线程等待服务器停止信号!");
            Demo.class.wait();
        }

        System.out.println("服务器停止!");

    }

    private static void setCookies(Socket socket, HttpServletRequest request) throws IOException {
        // /docs/page/   myname=john => cookie, 有效期 1周 默认不支持非西方文字
        OutputStream out = socket.getOutputStream();
        // 响应头行
        out.write("HTTP/1.1 200 OK\r\n".getBytes());
        // 头域参数
        out.write("ContentType: text/html;charset=UTF-8\r\n".getBytes());
        int time = 60 * 60 * 24 * 7;
        out.write(("Set-Cookie: myname=john; Max-Age=" + time + "; Path=/docs/page;\r\n").getBytes());
        // 空行
        out.write("\r\n".getBytes());

        out.write("<html>cookie 添加成功!</html>".getBytes());


    }

    /**
     * 查看cookie数据
     * @param socket
     */
    private static void showCookies(Socket socket, HttpServletRequest request) throws IOException {
        Map<String, String> headerMap = request.getHeaderMap();
        String cookieStr = headerMap.get("Cookie");
        String[] split = {};
        if(cookieStr != null) {
            split = cookieStr.split("; ");
        }

        OutputStream out = socket.getOutputStream();
        // 响应头行
        out.write("HTTP/1.1 200 OK\r\n".getBytes());
        // 头域参数
        out.write("ContentType: text/html;charset=UTF-8\r\n".getBytes());
        // 空行
        out.write("\r\n".getBytes());
        out.write(("<html>").getBytes());
        out.write("<ul>\n".getBytes());
        for (String s : split) {
            String[] nameAndValue = s.split("=");
            out.write("<li>\n".getBytes());
            out.write(String.format("%s = %s\n", nameAndValue[0], nameAndValue[1]).getBytes());
            out.write("</li>\n".getBytes());
        }
        out.write("</ul>\n".getBytes());
        out.write(("</html>").getBytes());

    }

    /**
     * 响应重定向
     * @param socket
     */
    private static void sendRedirect(Socket socket, String url) throws IOException {
        OutputStream out = socket.getOutputStream();
        // 响应头行
        out.write("HTTP/1.1 301 Redirect\r\n".getBytes());
        // 头域参数
        out.write(("Location: "+url+"\r\n").getBytes());
        // 空行
        out.write("\r\n".getBytes());
        // 没有响应体
    }

    public static void response(Socket socket, HttpServletRequest request) throws IOException {
        String filepath = WEBAPPS + request.getRequestURI();
        OutputStream out = socket.getOutputStream();
        // 响应头行
        out.write("HTTP/1.1 200 OK\r\n".getBytes());
        // 头域参数
        out.write("ContentType: text/html;charset=UTF-8\r\n".getBytes());
        // 空行
        out.write("\r\n".getBytes());
        // 响应体
        try(FileInputStream fis = new FileInputStream(filepath)){
            byte[] bytes = new byte[1024];
            int count;
            while((count = fis.read(bytes))>-1){
                out.write(bytes,0,count);
            }
        }
    }

    public static void respones404(Socket socket, HttpServletRequest request) throws IOException {
        OutputStream out = socket.getOutputStream();
        // 响应头行
        out.write("HTTP/1.1 404 Not Found\r\n".getBytes());
        // 头域参数
        out.write("ContentType: text/html;charset=UTF-8\r\n".getBytes());
        // 空行
        out.write("\r\n".getBytes());
        out.write(("<html>" +
                "<head><META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></head>" +
                "<body>" +
                "<h2>HTTP Status 404 – Not Found</h2>" +
                "<p>Message: "+request.getRequestURI()+"</p>" +
                "</body></html>").getBytes());
    }
}
